/*
 * @Author: 来自火星的码农 15122322+heyzhi@user.noreply.gitee.com
 * @Date: 2025-10-22 20:12:01
 * @LastEditors: 来自火星的码农 15122322+heyzhi@user.noreply.gitee.com
 * @LastEditTime: 2025-10-26 21:05:06
 * @FilePath: /server/workspace/src/net/address.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include "address.h"
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <netinet/in.h>
#include <ostream>
#include <sstream>
#include <stdexcept>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include "endian.h"
namespace Yizhi {

    int Address::getFamily() const{
        return getAddr()->sa_family;
    }

    bool Address::operator<(const Address& rhs) const{
        socklen_t minlen=std::min(getAddrLen(),rhs.getAddrLen());
        int result=memcmp(getAddr(),rhs.getAddr(),minlen);
        if(result<0){
            return true;
        }
        else if(result>0){
            return false;
        }
        else if(getAddrLen()<rhs.getAddrLen()){
            return true;
        }

        return false;
    }

    bool Address::operator==(const Address&rhs) const{
        return getAddrLen()==rhs.getAddrLen()&&memcmp(getAddr(),rhs.getAddr(),getAddrLen());
    }

    bool Address::operator!=(const Address&rhs) const{
        return !(*this==rhs);
    }

    std::string Address::tostring(){
        std::stringstream ss;
        insert(ss);
        return ss.str();
    }


    IPv4Address::IPv4Address(uint32_t address,uint32_t port){
        memset(&m_addr,0,sizeof(sockaddr_in));
        m_addr.sin_family=AF_INET;
        m_addr.sin_addr.s_addr=byteswapOnLittleEndian(address);
        m_addr.sin_port=byteswapOnLittleEndian(port);
    }

    socklen_t IPv4Address::getAddrLen()const{
        return sizeof(m_addr);
    }

    const sockaddr* IPv4Address::getAddr() const{
        return (sockaddr*)&m_addr;
    }

    std::ostream& IPv4Address::insert(std::ostream& os)const{
     
        uint32_t address=byteswapOnLittleEndian(m_addr.sin_addr.s_addr);
        os<<((address>>24)&(0Xff))<<"."
          <<((address>>16)&0Xff)<<"."
          <<((address>>8)&(0Xff))<<"."
          <<((address&0xff));


        uint32_t port=byteswapOnLittleEndian(m_addr.sin_port);

        os<<":"<<port;
        return os;
    }


    IPAddress::ptr IPv4Address::broadcastAddress(uint32_t prefix_len){
       return nullptr;
    }

    void IPv4Address::setPort(uint32_t v){
        m_addr.sin_port=byteswapOnLittleEndian(v);
    }

    uint32_t IPv4Address::getPort() const{
        return byteswapOnLittleEndian(m_addr.sin_port);
    }


    IPv6Address::IPv6Address(){
        memset(&m_addr,0,sizeof(m_addr));
        m_addr.sin6_family=AF_INET6;
    }

    IPv6Address::IPv6Address(const char* address,uint32_t port){
         memset(&m_addr,0,sizeof(m_addr));
         m_addr.sin6_family=AF_INET6;
         m_addr.sin6_port=byteswapOnLittleEndian(port);

         memcpy(&m_addr.sin6_addr.s6_addr,address, 16);
    }

    void IPv6Address::setPort(uint32_t v){
        m_addr.sin6_port=byteswapOnLittleEndian(v);
    }
    uint32_t IPv6Address::getPort()const{
        return byteswapOnLittleEndian(m_addr.sin6_port);
    }

    std::ostream& IPv6Address::insert(std::ostream& os)const{
        
        os<<"[";
        uint16_t* addr=(uint16_t*)m_addr.sin6_addr.s6_addr;

        bool used_zero=false;
        for(int i=0;i<8;i++){
            if(addr[0]==0&&!used_zero){
                continue;
            }
            if(i&&addr[i-1]==0&&!used_zero){
                os<<":";
                used_zero=true;
            }
            if(i){
                os<<":";
            }

            os<<byteswapOnLittleEndian(addr[i])<<std::dec;
        }
        if(addr[7]==0&&!used_zero){
            os<<"::";
        }

        os<<"]:"<<byteswapOnLittleEndian(m_addr.sin6_port);
        return os;
    }
    static const size_t MAX_PATH_SIZE=(sizeof((sockaddr_un*)0)->sun_path)-1;

    UnixAddress::UnixAddress(){
        memset(&m_addr,0,sizeof(m_addr));
        m_addr.sun_family=AF_UNIX;
        m_length=MAX_PATH_SIZE+offsetof(sockaddr_un,sun_path);
    }

    UnixAddress::UnixAddress(const std::string& path){
        memset(&m_addr,0,sizeof(m_addr));
        m_addr.sun_family=AF_UNIX;
        m_length=path.size()+1;
        if(!path.empty()&&path[0]=='\0'){
            --m_length;
        }

        if(m_length>sizeof(m_addr.sun_path)){
            throw std::logic_error("path too long");
        }

        memcpy(m_addr.sun_path,path.c_str(),m_length);
        m_length+=offsetof(sockaddr_un, sun_path);
    }

    const sockaddr* UnixAddress::getAddr()const{
        return (sockaddr*)&m_addr;
    }

    socklen_t UnixAddress::getAddrLen()const{
        return sizeof(m_addr);
    }
    
    std::ostream& UnixAddress::insert(std::ostream& os)const{
        if(m_length>offsetof(sockaddr_un, sun_path)&&m_addr.sun_path[0]=='\0'){
            return os<<"\\0"<<std::string(m_addr.sun_path+1,m_length-offsetof(sockaddr_un, sun_path));
        }
        os<<m_addr.sun_path;
        return os;
    }


    UnkownAddress::UnkownAddress(int family){
        memset(&m_addr,0,sizeof(m_addr));
        m_addr.sa_family=family;
    }

    socklen_t UnkownAddress::getAddrLen() const{
        return sizeof(m_addr);
    }
    const sockaddr* UnkownAddress::getAddr()const{
        return (sockaddr*)&m_addr;
    }
    
    std::ostream& UnkownAddress::insert(std::ostream& os) const{
        return os<<"unkown address family:["<<m_addr.sa_family<<":]";
    }





    





}